import React, { useState } from "react";
// 从immutable中导入用于处理对象的Map函数
import { Map, fromJS } from "immutable";

// 用法一：将定义的普通JS对象转换为immutable Map对象进行修改，再将修改后的转换成普通JS对象
let obj = {
    name: "x",
    age: 18,
};
// 1.根据obj获得转化后的immutable Map对象：oldObj
let oldObj = Map(obj);

// 2.在oldObj上进行修改
// set('key',value)修改immutable Map对象，支持链式调用，返回的是修改后的新immutable Map对象
// 注意：调用set的immutable Map对象（如：oldObj）本身并不会被修改
let newObj = oldObj.set("name", "Y").set("age", 20);
console.log(newObj, oldObj); // 打印的结果可以看到是immutable Map对象格式，oldObj并没有被修改
// get('key'),获取immutable Map对象上对应的值：immutable Map对象不能.属性获取值
console.log(newObj.get("name"), oldObj.get("name")); // Y，X

// 3.将修改后的immutable Map对象：newObj转换成putJS对象
// toJS()返回将immutable Map对象转换成的普通JS对象
let obj2 = newObj.toJS();
console.log(obj2);
// 只需上述三步：Map转换，set修改，toJS回转
// 即可实现深拷贝数据修改后得到修改后的新数据且不影响原数据

// 用法二：直接将原数据定义成immutable Map对象，直接使用set进行修改，得到修改后的immutable Map对象
// let obj3 = Map({
//     name: "x",
//     age: 18,
// });
// let obj4 = obj3.set("name", "Y").set("age", 20);
// console.log(obj4);

// ---------------------------------------------------------------------

// 注意：对于多层的对象，每一层都需要进行Map转换
// 这是在知道对象数据结构时手动一层层的进行Map包裹
// let obj5 = Map({
//     love: Map({
//         name: "小明",
//     }),
// });
// 在不知道对象数据结构时怎么一层层的进行Map包裹呢？使用fromJS()
// 在最外层使用immutable导出的fromJS包裹能直接将复杂的结构转换好，包括数组
let obj5 = fromJS({
    love: {
        name: "小明",
    },
});
console.log(obj5);

// 对于这种嵌套的怎么修改内层的属性呢？
// 为了修改name，这里使用set很麻烦，要先获取love的值，将其name修改后得到新的love值，再根据这个新值修改love
// let newObj5 = obj5.set("love", obj5.get("love").set("name", "小红")); // 麻烦，使用setIn更简单
let newObj5 = obj5.setIn(["love", "name"], "小红"); // setIn([key1,key2,...],newValue) 修改多层嵌套的值

console.log(newObj5.getIn(["love", "name"])); // 小红 // getIn([key1,key2,...]) 获取多层嵌套的值
console.log(newObj5.get("love").get("name")); // 小红

// 小技巧：直接使用fromJS和toJS进行深拷贝
let obj6 = {
    name: "x",
    age: 18,
    love: {
        name: "Y",
    },
};
let obj7 = fromJS(obj6).toJS(); // 直接深拷贝
obj7.name = "小明";
obj7.love.name = "小红";
console.log(obj6, obj7);

// React中两种使用方式
// 一：状态定义时直接定义成immutable格式
export default function App() {
    // const [data, setdata] = useState( // 笨方法
    //     Map({
    //         love: Map({
    //             name: "小明",
    //             age: "18",
    //         }),
    //     })
    // );
    const [data, setdata] = useState(
        fromJS({
            love: {
                name: "小明",
                age: "18",
            },
        })
    );
    return (
        <div>
            <h1>immutable Map的使用:</h1>
            <button
                onClick={() => {
                    // setdata( // 笨方法
                    //     data.set("love", data.get("love").set("name", "小红"))
                    // );
                    setdata(data.setIn(["love", "name"], "小红"));
                }}>
                修改
            </button>
            {/* // 笨方法： {data.get("love").get("name")}--{data.get("love").get("age")}  */}
            {data.getIn(["love", "name"])}--{data.getIn(["love", "age"])}
            <hr />
            <App2></App2>
        </div>
    );
}
// 二：状态定义为普通JS对象，在修改时再进行转换
function App2() {
    const [data, setdata] = useState({
        love: {
            name: "小明",
            age: "18",
        },
    });
    return (
        <div>
            <h1>immutable Map的使用:</h1>
            <button
                onClick={() => {
                    // 1. fromJS转换成immutable对象
                    // 2. setIn修改
                    // 3. toJS回转成普通JS对象
                    // 4.  setdata(newData)更新状态
                    // const newData = fromJS(data)
                    //     .setIn(["love", "name"], "小红")
                    //     .toJS();
                    let newData = fromJS(data).toJS();
                    newData.love.name = "小红";
                    setdata(newData);
                }}>
                修改
            </button>
            {data.love.name}--{data.love.age}
        </div>
    );
}
